package com.power.sifa.approve.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.plf.common.domain.ResponseDTO;
import com.power.flowable.api.IPersonalFeign;
import com.power.sifa.approve.dao.Apl_admreviewDao;
import com.power.sifa.approve.dao.Apl_mainDao;
import com.power.sifa.approve.dao.Aprv_process_materialsDao;
import com.power.sifa.approve.model.Apl_admreview;
import com.power.sifa.approve.model.Apl_main;
import com.power.sifa.approve.model.Aprv_process_materials;
import com.power.sifa.approve.model.enumeration.*;
import com.power.sifa.approve.service.Apl_admreviewService;
import com.power.sifa.approve.service.Apl_archiveService;
import com.power.sifa.approve.service.Apl_dossierService;
import com.power.sifa.approve.service.ProcessApproveService;
import com.power.sifa.correction.model.pojo.bo.AutoEndCaseBO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ProcessApproveServiceImpl implements ProcessApproveService {


    @Resource
    private Aprv_process_materialsDao aprv_process_materialsDao;

    @Resource
    private Apl_admreviewService apl_admreviewService;

    @Resource
    private IPersonalFeign personalFeign;

    @Resource
    private Apl_archiveService apl_archiveService;

    @Resource
    private Apl_dossierService apl_dossierService;

    @Resource
    private Apl_mainDao apl_mainDao;

    @Resource
    private Apl_admreviewDao apl_admreviewDao;


    @Override
    public ResponseDTO passRecord(String applyid, String category) {
        Tp_proctypeEnum proctypeEnum = Tp_proctypeEnum.getByCategoryKey(category);
        if (ObjectUtil.isNull(proctypeEnum) || CollectionUtil.isEmpty(proctypeEnum.getMaterilas())) {
            return new ResponseDTO(0, "无需校验");
        }
        if (proctypeEnum.equals(Tp_proctypeEnum.HEAR_DECISION)) {
            // 查询当前的案件的程序类型，若是简易程序和一般程序必填项不一样, 简易程序不展示听证调查表,普通程序仍然需要校验文件
            Apl_admreview admreviewObj = this.apl_admreviewService.getById(applyid);
            // 普通程序
            if (ObjectUtil.isNotNull(admreviewObj) &&  Tp_apptype.ORDINARY == admreviewObj.getProctype()) {
                return this.mediateCheck(applyid, proctypeEnum.getId(), proctypeEnum.getMaterilas());
            }
            return new ResponseDTO(0, "无需校验");
        }
        return this.mediateCheck(applyid, proctypeEnum.getId(), proctypeEnum.getMaterilas());
    }
    /**
     * 校验调解的材料是否上传完整
     *
     * @param applyid
     * @return
     */
    private ResponseDTO mediateCheck(String applyid, Integer type, List<Tp_procmaterialEnum> materialType) {
        Specification<Aprv_process_materials> specification = (root, query, criteriaBuilder) -> query.where(
                criteriaBuilder.and(criteriaBuilder.equal(root.get("applyid"), applyid),
                        criteriaBuilder.equal(root.get("type"), type))
        ).getRestriction();
        List<Aprv_process_materials> materials = aprv_process_materialsDao.findAll(specification);
        List<Integer> materialIds = materialType.stream().map(Tp_procmaterialEnum::getId).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(materials)) {
            return ResponseDTO.wrap(-1,
                    "请上传" + String.join(",", materialType.stream().map(Tp_procmaterialEnum::getDesc).collect(Collectors.toList()).toArray(new String[materialType.size()])));
        }
        List<Integer> queryMaterialTypes = materials.stream().map(Aprv_process_materials::getMattype).distinct().collect(Collectors.toList());
        if (queryMaterialTypes.containsAll(materialIds)) {
            return ResponseDTO.succMsg("材料上传完整");
        } else {
            List<String> materialNames = materialType.stream().filter(item -> !queryMaterialTypes.contains(item.getId())).map(Tp_procmaterialEnum::getDesc)
                    .collect(Collectors.toList());
            return ResponseDTO.wrap(-1, "请上传" + String.join(",", materialNames.toArray(new String[materialNames.size()])));
        }
    }



    @Transactional(rollbackFor = {Exception.class})
    public void autoEndCase(AutoEndCaseBO endCase) {
        Specification<Apl_main> specification = (root, query, criteriaBuilder) -> query.where(criteriaBuilder.equal(root.get("acceptcode"), endCase.getAcceptcode())).getRestriction();
        List<Apl_main> mainList = this.apl_mainDao.findAll(specification);
        List<Apl_main> mainProcessList = mainList.stream().filter(el -> ObjectUtil.isNotNull(el.getApplycode())).collect(Collectors.toList());
        List<Apl_main> subProcesList = mainList.stream().filter(el -> (ObjectUtil.isNull(el.getApplycode()) && ObjectUtil.isNull(el.getFinishtime()))).collect(Collectors.toList());
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (CollectionUtil.isNotEmpty(subProcesList)) {
            if (CollectionUtil.isNotEmpty(subProcesList)) {
                subProcesList.stream().forEach(el -> {
                    if (ObjectUtil.isNotNull(endCase.getDealDate()) && ObjectUtil.isNull(el.getAccepttime())) {
                        el.setAccepttime(format.format(endCase.getDealDate()));
                    }
                    if (ObjectUtil.isNotNull(endCase.getFinishDate()) && ObjectUtil.isNull(el.getFinishtime())) {
                        el.setFinishtime(format.format(endCase.getFinishDate()));
                    }
                    // 设置状态完结
                    el.setStatus(St_apply.FINISH);
                });
            }
            if (CollectionUtil.isNotEmpty(subProcesList)) {
                subProcesList.stream().forEach(el -> {
                    ResponseDTO res = this.personalFeign.getTaskByInstid(el.getInstid());
                    if (res.getCode() == 0) {
                        ResponseDTO resClaim = this.personalFeign.claimTask((String) res.getData(), el.getReguserid());
                        if (resClaim.getCode() == 0) {
                            ResponseDTO res2 = this.personalFeign.terminationTask(el.getReguserid(), null, null, res.getData().toString(), null, "自动办结", new ArrayList<Map<String, Object>>());
                            Map<String, Object> res2Data = (Map<String, Object>) res2.getData();
                            if (res2Data.get("code").equals(Integer.valueOf(0))) {
                                log.info("子流程关闭成功：" + endCase.getAcceptcode() + res.getData());
                            } else {
                                log.info("子流程关闭失败：" + endCase.getAcceptcode() + res.getData());
                                log.info("子流程关闭失败详情：" + JSON.toJSONString(res2Data));
                            }
                        }
                    }
                });
            }
            //  子流程更新
            this.apl_mainDao.saveAll(subProcesList);
        }
        if (CollectionUtil.isNotEmpty(mainProcessList)) {
            Apl_main mainProcess = mainProcessList.get(0);
            if (ObjectUtil.isNull(mainProcess.getFinishtime())) {
                if (ObjectUtil.isNotNull(endCase.getDealDate()) && ObjectUtil.isNull(mainProcess.getAccepttime())) {
                    mainProcess.setAccepttime(format.format(endCase.getDealDate()));
                }
                if (ObjectUtil.isNotNull(endCase.getFinishDate()) && ObjectUtil.isNull(mainProcess.getFinishtime())) {
                    mainProcess.setFinishtime(format.format(endCase.getFinishDate()));
                }
                mainProcess.setStatus(St_apply.FINISH);
                Apl_admreview admreview = this.apl_admreviewDao.getById(mainProcess.getId());
                if (ObjectUtil.isNotNull(admreview)) {
                    admreview.setStatus(St_admreview.HEAR);
                    admreview.setDecisiontype(Integer.valueOf(endCase.getCaseResult()));
                    admreview.setDecisiontypeid(Integer.valueOf(endCase.getCaseDetail()));
                    // 子流程置空
                    admreview.setSonstatus(null);
                }
                ResponseDTO res = this.personalFeign.getTaskByInstid(mainProcess.getInstid());
                if (res.getCode() == 0) {
                    ResponseDTO resClaim = this.personalFeign.claimTask((String) res.getData(), mainProcess.getReguserid());
                    if (resClaim.getCode() == 0) {
                        ResponseDTO res2 = this.personalFeign.terminationTask(mainProcess.getReguserid(), null, null, res.getData().toString(), null, "自动办结", new ArrayList<Map<String, Object>>());
                        Map<String, Object> res2Data = (Map<String, Object>) res2.getData();
                        if (res2Data.get("code").equals(Integer.valueOf(0))) {
                            log.info("主流程关闭成功：" + endCase.getAcceptcode() + res.getData());
                        } else {
                            log.info("主流程关闭失败：" + endCase.getAcceptcode() + res.getData());
                            log.info("主流程关闭失败详情：" + JSON.toJSONString(res2Data));
                        }
                    }
                }
                // 主流程更新
                this.apl_mainDao.save(mainProcess);
                this.apl_admreviewDao.save(admreview);
            }
            CompletableFuture.runAsync(() -> {
                try {
                    this.apl_archiveService.initialArchiveData(mainProcess.getId());
                    this.apl_dossierService.buildInitDossier(mainProcess.getId());
                } catch (Exception e) {
                    log.error("归档生成报错:" + e.getMessage());
                }
            });
        }
    }



}
